package com.cloud.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.cloud.common.constants.HeaderConstant;
import com.cloud.common.response.SimpleResponse;
import com.cloud.common.syse.HttpCodeE;
import com.cloud.common.syse.SysRespStatusE;
import com.cloud.common.utils.ApiSign;
import com.cloud.common.utils.ValidationUtils;
import com.cloud.gateway.config.SignPassUrlConfig;
import com.cloud.gateway.utils.ServerWebExchangeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
@RefreshScope
public class SignFilter implements GlobalFilter, Ordered {

    @Autowired
    private SignPassUrlConfig signPassUrlConfig;

    @Value("${url.expiration.time}")
    private Long urlConnectionExpirationTime;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        List<String> skipAuthUrls = signPassUrlConfig.getIgnoredSignPath();
        //获取请求  响应
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse originalResponse = exchange.getResponse();
        // 获取请求头
        HttpHeaders headers = request.getHeaders();
        //获取url
        String url = request.getURI().getPath();
        //跳过不需要验证的路径
        if (null != skipAuthUrls && skipAuthUrls.contains(url)) {
            //放行
            return chain.filter(exchange);
        }
        //参数签名验证
        if (signPassUrlConfig.getSignFlag()) {
            String channelType = headers.getFirst(HeaderConstant.CHANNELTYPE);
            String requestId = headers.getFirst(HeaderConstant.REQUESTID);
            String sign = headers.getFirst(HeaderConstant.SIGN);
            String timestamp = headers.getFirst(HeaderConstant.TIMESTAMP);
            if (ValidationUtils.isStrsNull(channelType, requestId, sign, timestamp)) {
                DataBuffer buffer = this.getReturnBuffer(originalResponse, "参数传入错误");
                return originalResponse.writeWith(Flux.just(buffer));
            }
            if(!ValidationUtils.isSTR_NUM(timestamp)){
                DataBuffer buffer = this.getReturnBuffer(originalResponse, "timestamp必须是数字");
                return originalResponse.writeWith(Flux.just(buffer));

            }
            if((new Date().getTime()-Long.parseLong(timestamp))>urlConnectionExpirationTime){
                DataBuffer buffer = this.getReturnBuffer(originalResponse, "连接已过期请重试");
                return originalResponse.writeWith(Flux.just(buffer));
            }
            Map<String, String> parameterString = ServerWebExchangeUtils.getParam(exchange);
            log.info("请求地址:{},参数:{}",url,JSON.toJSONString(parameterString));
            parameterString.put(HeaderConstant.TIMESTAMP,timestamp);
            parameterString.put(HeaderConstant.REQUESTID,requestId);
            parameterString.put(HeaderConstant.CHANNELTYPE,channelType);
            //sign 签名约定好的盐 作为一个请求参数进行拼接，不用放在请求头header里面
            parameterString.put(HeaderConstant.SIGNSALT, signPassUrlConfig.getSignSalt());
            String mySign = ApiSign.getSignature(parameterString);
            log.info("我的签名结果mySign={}",mySign);
            if(!sign.equals(mySign)){
                DataBuffer buffer = this.getReturnBuffer(originalResponse, "签名失败");
                return originalResponse.writeWith(Flux.just(buffer));
            }else {
                return chain.filter(exchange);
            }
        }else{
            Map<String, String> parameterString = ServerWebExchangeUtils.getParam(exchange);
            log.info("请求地址:{},参数:{}",url,JSON.toJSONString(parameterString));
            return chain.filter(exchange);
        }

    }

    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * 返回给前端json相关数据方法
     * @param originalResponse
     * @return
     */
    private DataBuffer getReturnBuffer(ServerHttpResponse originalResponse,String message) {
        originalResponse.setStatusCode(HttpStatus.OK);
        originalResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        SimpleResponse resp=new SimpleResponse();
        resp.setReturnErrMsg(resp, HttpCodeE.参数有误.value, SysRespStatusE.失败.getDesc(), message);
        DataBuffer buffer = originalResponse.bufferFactory().wrap(JSON.toJSONString(resp).getBytes());
        return buffer;
    }


}
